
import { lazyReport } from './report';
import ErrorStackParser from "error-stack-parser";
import stringify from "json-stringify-safe";
import Vue from 'vue'

// eventid 事件id
// user // 用户上报
// customerOptions: //用户上报  用户自定义的额外平台参数信息，例如poin版本、平台语言、是否是某个特殊业务等等
// processEnv: prod // 用户上报

// type: error 
// createdDate // sdk生成
// url // sdk生成
// device // sdk生成
// message // sdk生成
// target // sdk生成
// col // sdk生成
// row // sdk生成
// error // sdk生成
// errorType: jsError、 promiseError 、resourceError、 vueError
// stackTrace //sdk生成 错误堆栈
// status: //sdk生成  "happen", "assgined", "fixed"

// fixedDate // 后台生成
// fixed_man // 后台生成

const getComponentNameTrace = (vm) => {
  const compTrace = [formatComponentName(vm)];
  while (vm.$parent) {
    vm = vm.$parent;
    compTrace.unshift(formatComponentName(vm));
  }

  return compTrace;
};

const formatComponentName = (vm) => {
  try {
    if (vm.$root === vm) return "root";

    const name = vm._isVue
      ? (vm.$options && vm.$options.name) ||
        (vm.$options && vm.$options._componentTag)
      : vm.name;
    return (
      (name ? "component <" + name + ">" : "anonymous component") +
      (vm._isVue && vm.$options && vm.$options.__file
        ? " at " + (vm.$options && vm.$options.__file)
        : "")
    );
  } catch (error) {
    throw new Error(typeof error === "string" ? error : "");
  }
};

/**
 * 全局错误捕获
 */
export function errorTrackerReport() {
  // --------  js error ---------
  const originOnError = window.onerror;

  // 运行异常，js异常
  window.onerror = function (msg, url, row, col, error) {
    // 处理原有的onerror
    
    if (originOnError) {
      originOnError.call(window, msg, url, row, col, error);
    }
    const stackTrace = error ? ErrorStackParser.parse(error) : [];
    const ErrorEntity = {
      message: msg,
      // error,
      errorType: 'jsError',
      file: url,
      row,
      col,
      stackTrace: stringify(stackTrace),
    }
    // 错误上报
    console.log("lsls1", stringify(stackTrace))
    lazyReport('error', ErrorEntity);
  }

  // ------  promise error  --------
  window.addEventListener('unhandledrejection', (error) => {
    console.log("sss", error)
    if (Object.prototype.toString.call(error.reason) === "[object Object]") {
      const ErrorEntity = {
        message: error.reason.name,
        error: JSON.stringify(error.reason),
        errorType: 'promiseError',
        stackTrace: stringify(error.reason.stack),
      }
      lazyReport('error', ErrorEntity);
    } else {
      const ErrorEntity = {
        message: error.reason,
        error: JSON.stringify(error),
        errorType: 'promiseError'
      }
      console.log("lsls2", error.reason)
      lazyReport('error', ErrorEntity);
    }
    
  });

  // ------- resource error --------
  window.addEventListener('error', (error) => {
    
    let target = error.target;
    let isElementTarget = target instanceof HTMLScriptElement || target instanceof HTMLLinkElement || target instanceof HTMLImageElement;
    if (!isElementTarget) {
      return; // js error不再处理
    }
    const ErrorEntity = {
      message: "加载 " + target.tagName + " 资源错误",
      file: target.src,
      errorType: 'resourceError'
    }
    console.log("lsls3", error)
    console.log("error1113", ErrorStackParser.parse(error))
    lazyReport('error', ErrorEntity);
  }, true);

  Vue.config.errorHandler = function (err, vm, info) {
    // 处理错误
    const stackTrace = err ? ErrorStackParser.parse(err) : [];
    const errorType = "vueError";

    const ErrorEntity = {
      errorType,
      message: err.message,
      stackTrace: stringify(stackTrace),
      info,
    }
    try {
      if (vm) {
        const propsData = vm.$options && vm.$options.propsData;
        ErrorEntity.componentName = formatComponentName(vm);
        ErrorEntity.componentNameTrace = getComponentNameTrace(vm);
        ErrorEntity.propsData =propsData
      }
    } catch (error) {
      console.log(error)
      throw new Error(typeof error === "string" ? error : "");
    }
    lazyReport('error', ErrorEntity);
  };


  // VueConstructor.config.errorHandler = (err, vm, info) => {
  //  console.log("111222", err, vm, info)
  // };
}

/**
 * 手动捕获错误
 */
export function errorCaptcher(error, msg) {
  // 上报错误
  console.log("4", {
    message: msg,
    error: error,
    errorType: 'catchError'
  })
  lazyReport('error', {
    message: msg,
    error: error,
    errorType: 'catchError'
  });
}